namespace	Z	{

//------------------------------------------------------------------------------------------------------------------------
template<typename Derived>
Win32Console<Derived>::Win32Console()
:	mRoot(new Root),
	mQuit(false)
{
}

template<typename Derived>
Win32Console<Derived>::~Win32Console()
{
}

template<typename Derived>
bool Win32Console<Derived>::initialise()
{
	if(!::SetConsoleCtrlHandler((PHANDLER_ROUTINE)Win32Console::consoleCtrlHandler, TRUE))
		return false;
	if(!Socket::loadLib())
		return false;
	if(!startProcessing())
		return false;
	return true;
}

template<typename Derived>
void Win32Console<Derived>::finalise()
{
	stopProcessing();
	Socket::unloadLib();
}

template<typename Derived>
BOOL Win32Console<Derived>::consoleCtrlHandler(DWORD dwEvent)
{
	switch(dwEvent)	{
		case CTRL_C_EVENT:
		case CTRL_BREAK_EVENT:
			return TRUE;
		case CTRL_LOGOFF_EVENT:
		case CTRL_SHUTDOWN_EVENT:
		case CTRL_CLOSE_EVENT:
			Derived::getSingleton().finalise();
			return FALSE;
	}
	return TRUE;
}

template<typename Derived>
void Win32Console<Derived>::processCommand()
{
	printPrompt();
	while(handle(::getchar()));
}

template<typename Derived>
bool Win32Console<Derived>::handle(char command)
{
	switch(command)	{
		case 'q':
		case 'Q':
			return false;
		case 10:
			printPrompt();
			break;
	}
	return true;
}

template<typename Derived>
void Win32Console<Derived>::printPrompt()
{
	std::cout << ">";
}

template<typename Derived>
bool Win32Console<Derived>::startProcessing()
{
	mQuit	= false;
	mProcess.reset(new boost::thread(boost::bind(&Win32Console::process, this)));
	return mProcess->joinable();
}

template<typename Derived>
void Win32Console<Derived>::stopProcessing()
{
	mQuit	= true;
	mProcess->join();
	mProcess.reset();
}

template<typename Derived>
void Win32Console<Derived>::process()
{
	const float kIdealDeltaSeconds	= 1.0f / 60.0f;
	float dtSeconds	= kIdealDeltaSeconds;
	int64 kBegin	= readHiResTimer();

	while(!mQuit)	{
		doProcess(dtSeconds);
		int64 kEnd	= readHiResTimer();
		dtSeconds	= (float32)(kEnd - kBegin)
							/ (float32)readHiResTimerFrequency();
		kBegin	= kEnd;
		const ms_t ms	= (ms_t)(std::max<float>(kIdealDeltaSeconds - dtSeconds, 0.0f) * 1000.0f);
		::Sleep(ms);
	}
}

}